package pritace

import (
	"fmt"
	"reflect"
)

type User struct {
	Name string
	Age  int
	Sex  bool
}

type student struct {
	Class string
	User
}

func (u User) SayName(name string) {
	fmt.Println("我的名字叫做", name)
}

func ReflectMain() {
	u := User{
		Name: "Bob",
		Age:  35,
		Sex:  true,
	}
	s := student{"三年二班", u}

	// check(s)
	// reflectCheck(s)
	changeCheck(&s)

}

// 普通的断言方式
func check(v interface{}) {
	// v.(User).SayName("test")
	switch v.(type) {
	case User:
		fmt.Println(v.(User).Name)
		fmt.Println("我是User")
	case student:
		fmt.Println(v.(student).Class)
		fmt.Println("我是student")
	}
}

// 运用反射的方式
func reflectCheck(inter interface{}) {

	t := reflect.TypeOf(inter)
	v := reflect.ValueOf(inter) //v = {Bob 35 true}

	//获取v中的值
	for i := 0; i < t.NumField(); i++ {
		fmt.Println(v.Field(i))
	}
	fmt.Println(t, v)                        //main.student {三年二班 {Bob 35 true}}
	fmt.Println(v.FieldByIndex([]int{1, 0})) //Bob
	fmt.Println(v.FieldByName("Class"))      //三年二班

}

func changeCheck(inter interface{}) {
	v := reflect.ValueOf(inter)
	e := v.Elem()
	fmt.Println(e)

	//通过反射改变原始数据的值
	e.FieldByName("Class").SetString("四年二班")
	fmt.Println(inter)
}

func PtrReflectTest()  {
	type cat struct {

	}
	ins := &cat{}
	typeOfCat := reflect.TypeOf(ins)
	fmt.Printf("name:%v kind:%v\n", typeOfCat.Name(), typeOfCat.Kind())
	// 取类型的元素
	typeOfCat = typeOfCat.Elem()
	fmt.Printf("name:%v kind:%v\n", typeOfCat.Name(), typeOfCat.Kind())
}

